// 模型
import * as Cesium from 'cesium'

export default {
  /**
   * @function 加载模型
   * {Viewer} viewer
   * {String} url
  */
  loadGltfModel (viewer, url, options) {
    var scene = viewer.scene
    let destination = options.destination || {}
    let orientation = options.orientation || {}
    let form = Object.assign({}, {
      heading: 0,
      pitch: 0,
      roll: 0,
      scale: 1,
      offsetX: 0,
      offsetY: 0,
      offsetZ: 0,
    }, orientation, options)
    // 确定矩阵变化的原点
    let origin = Cesium.Cartesian3.fromDegrees(destination.lng, destination.lat, destination.height)
    let transform = Cesium.Transforms.eastNorthUpToFixedFrame(origin)
    // 缩放
    let scale = Cesium.Matrix4.fromScale(new Cesium.Cartesian3(form.scale, form.scale, form.scale));
    Cesium.Matrix4.multiply(transform, scale, transform);
    // 平移
    let translation = Cesium.Matrix4.fromTranslation(new Cesium.Cartesian3(form.offsetX, form.offsetY, form.offsetZ));
    Cesium.Matrix4.multiply(transform, translation, transform);
    // 旋转
    let heading = Cesium.Math.toRadians(form.heading);
    let pitch = Cesium.Math.toRadians(form.pitch);
    let roll = Cesium.Math.toRadians(form.roll);
    let hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
    let matrix3 = Cesium.Matrix3.fromHeadingPitchRoll(hpr);
    let rotation = Cesium.Matrix4.fromRotationTranslation(matrix3);
    Cesium.Matrix4.multiply(transform, rotation, transform);
    return new Promise((resolve, reject) => {
      try {
        var model = scene.primitives.add(Cesium.Model.fromGltf({
          url: url, // gltf文件的URL
          modelMatrix: transform,
          scale: 1,   //放大倍数
        }))
        model.readyPromise.then((res) => {
          // 设置
          model.modelMatrix = transform
          resolve({ model, res })
        })
      } catch (e) {
        console.log(e)
        reject(e)
      }
    })
  },

  // 3dtiles
  loadThreeDTiles (viewer, url, options) {
    // 开启地形深度检测:
    // 控制在渲染场景时，相机是否进行深度测试以避免将被遮挡的物体绘制在前景
    // true: 相机会根据地形高度信息进行深度测试，避免将低于地面的物体绘制在地面之上
    viewer.scene.globe.depthTestAgainstTerrain = true
    let destination = options.destination || {}
    // ! 写法一：将在 1.107 版本后不支持，options.url和Cesium3DTileset.readyPromise将被移除
    return new Promise((resolve, reject) => {
      viewer.scene.globe.depthTestAgainstTerrain = true
      const tileset = viewer.scene.primitives.add(
        new Cesium.Cesium3DTileset({
          url: url, // 模型切瓦后的瓦片索引文件地址或者Cesium Resource
          maximumScreenSpaceError: 1,
          maximumMemoryUsage: 1024,
          dynamicScreenSpaceError: true,
          cullWithChildrenBounds: false
        })
      )
      try {
        tileset.readyPromise.then((tileset) => {
          let boundingSphere = tileset.boundingSphere // 模型的范围
          boundingSphere.center = Cesium.Cartesian3.fromDegrees(destination.lng, destination.lat, destination.height)
          let cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center) // 从笛卡尔位置创建一个新的位置实例（返回的是一个经纬度的）
          let surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0) // 以经纬度的值来返回Cartesian3(xyz)的位置 
          let offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 50) // 以经纬度的值来返回Cartesian3(xyz)的位置 
          let translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3()) // 计算两个笛卡尔的分量差异
          tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation)
          resolve(tileset) // 返回模型对象
        })
      } catch (error) {
        console.log(`Error loading tileset: ${error}`)
        reject(error)
      }
    })
  },
  // setTimeout(function(){
  //   setLight(tileset)
  //   viewer.zoomTo(
  //     tileset,
  //     new Cesium.HeadingPitchRange(
  //       0.0,
  //       -0.5,
  //       tileset.boundingSphere.radius * 2.0 // 模型的包围球半径的2倍
  //     )
  //   )
  // },1000)
  // 传入3DTileS对象 设置泛光
  setLight (tiles) {
    const shader = `
      varying vec3 v_positionEC;
      void main(void){
        vec4 position = czm_inverseModelView * vec4(v_positionEC,1); // 位置
        float glowRange = 100.0; // 光环的移动范围(高度)
        gl_FragColor = vec4(0.0, 0.3, 0.8, 0.8); // 颜色1
        //  gl_FragColor = vec4(220.0, 0.3, 0.8, 0.8); // 颜色2
        // 低于10米的楼不显示渐变色
          if(position.z < 10.0) {
          gl_FragColor *= vec4(vec3(position.z / 10.0 * 2.0), 1.0);
        }else{
          gl_FragColor *= vec4(vec3(position.z / 10.0), 0.8); // 渐变
        }
        // 设置动态光环
        float time = fract(czm_frameNumber / 360.0);
        time = abs(time - 0.5) * 1.0;
        float diff = step(0.005, abs( clamp(position.z / glowRange, 0.0, 1.0) - time));
        gl_FragColor.rgb += gl_FragColor.rgb * (1.0 - diff);
      }
      `;

    tiles.tileVisible.addEventListener(function (tile) {
      const content = tile.content
      const featuresLength = content.featuresLength
      let feature
      for (var i = 0; i < featuresLength; i += 2) {
        feature = content.getFeature(i)
        const _model = feature.content._model
        _model._shouldRegenerateShaders = true
        Object.getOwnPropertyNames(_model._sourcePrograms).forEach(function () {
          const _modelSourceP = _model._sourcePrograms[0]
          _model._rendererResources.sourceShaders[_modelSourceP.fragmentShader] = shader
          if(_model._sourcePrograms[1] != undefined){
          const _modelSourceP1 = _model._sourcePrograms[1]
                _model._rendererResources.sourceShaders[_modelSourceP1.fragmentShader] = shader
          }
        })
        _model._shouldRegenerateShaders = true
      }
    })
  },
  // 设置模型高度
  setHeight(tileset, height) {
    height = Number(height)
    if (isNaN(height)) {
      return
    }
    var cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center)
    var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height)
    var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude,height)
    var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3())
    tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation)
  }
}